#include <gccore.h>
#include <malloc.h>
#include <ogc/ios.h>
#include <ogc/isfs.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "network.h"
#include "tools.h"
#include "filelog.h"

static netconfig_t *netconfig = NULL;
static const char *vencryption[] = {"Open", "WEP64", "WEP128", "", "WPA-PSK (TKIP)", "WPA2-PSK (AES)", "WPA-PSK (AES)"};

enum {
	INTERFACE = 0,
	DNS_SOURCE,
	IP_SOURCE,
	PROXY = 4,
	INTERNET_TEST,
	CONNECTION_SELECTED = 7
};  // Network flag shift operators

enum {
	ENCRYPT_OPEN = 0,
	ENCRYPT_WEP_64,
	ENCRYPT_WEP_128,
	ENCRYPT_WPA_PSK_TKIP = 4,
	ENCRYPT_WPA2_PSK_AES,
	ENCRYPT_WPA_PSK_AES
}; // Types of network encryption

#define FLAG(x) (netconfig->connection[slot].flags & (1<<(x)))

//---------------------------------------------------------------------------------
bool NetworkInit(void) {
//---------------------------------------------------------------------------------
	bool ret;
	s32 fd = ISFS_Open("/shared2/sys/net/02/config.dat", 1 );
	if (fd < 0) return false;
	netconfig = (netconfig_t*)memalign(32, sizeof(netconfig_t));
	memset(netconfig, 0, sizeof(netconfig_t));
	ret = ISFS_Read(fd, netconfig, 7004) == 7004; // 7004 = size of config.dat
	ISFS_Close(fd);
	ISFS_Deinitialize();
	return ret;
}

//---------------------------------------------------------------------------------
void NetworkDeinit(void) {
//---------------------------------------------------------------------------------
	if (netconfig) free(netconfig);
	NetworkInitialized = false;
	return;
}
 
 //---------------------------------------------------------------------------------
void NetworkProxy(proxy_t proxy_settings) {
//---------------------------------------------------------------------------------
	printf(CYAN "\tProxy: " WHITE "%s\n", proxy_settings.use_proxy ? "Enabled" : "Disabled");
	Log("\tProxy: %s\r\n", proxy_settings.use_proxy ? "Enabled" : "Disabled");
	if (!proxy_settings.use_proxy) return;

	printf(MAGENTA "\t\tUse Username\\Password: " WHITE "%s\n", proxy_settings.use_proxy_userandpass ? "Yes" : "No");
	Log("\t\tUse Username\\Password: %s\r\n", proxy_settings.use_proxy_userandpass ? "Yes" : "No");

	printf(MAGENTA "\t\tProxy Name: " WHITE "%s\n", proxy_settings.proxy_name);
	Log("\t\tProxy Name: %s\r\n", proxy_settings.proxy_name);
	
	printf(MAGENTA "\t\tProxy Port: " WHITE "%u\n", proxy_settings.proxy_port);
	Log("\t\tProxy Port: %u\r\n", proxy_settings.proxy_port);

	if (proxy_settings.use_proxy_userandpass) {
		printf(MAGENTA "\t\tProxy Username: " WHITE "%s\n", proxy_settings.proxy_username);
		Log("\t\tProxy Username: %s\r\n", proxy_settings.proxy_username);

		printf(MAGENTA "\t\tProxy Password: " WHITE "%s\n", proxy_settings.proxy_password);
		Log("\t\tProxy Password: %s\r\n", proxy_settings.proxy_password);
	}

	return;
}

//---------------------------------------------------------------------------------
void NetworkEncryption(u8 slot) {
//---------------------------------------------------------------------------------
	int i;
	u8 length = netconfig->connection[slot].key_length;
	printf(CYAN "\tEncryption Key: " WHITE);
	Log("\tEncryption Key: Not logged for security reasons\r\n");
	if (netconfig->connection[slot].encryption == ENCRYPT_OPEN) {
		printf("No encryption\n");
	} else {
		if (length == 0) // WEP64 or WEP128
			length = 4 + 4 * (netconfig->connection[slot].encryption == ENCRYPT_WEP_128);
		for(i=0; i < length; i++) {
			printf("%c", netconfig->connection[slot].key[i]);
			if (netconfig->connection[slot].key[i] == 0) break;
		}
		printf("\n");
	}
}

//---------------------------------------------------------------------------------
void NetworkInfo(u8 slot) {
//---------------------------------------------------------------------------------
	if ((slot > 2) || (slot < 0)) return;
	CHANGE_COLOR(YELLOW);
	printf("Connection %u:\n", slot + 1);
	Log("Connection %u:\r\n", slot + 1);
	if((FLAG(INTERFACE) == 0) && (netconfig->connection[slot].ssid_length == 0)) {
		printf(RED "\n\tNo Entry\n");
		Log("\tNo Entry\r\n");
	} else {
		printf(CYAN "\tConnection Type:" WHITE " %s\n", FLAG(INTERFACE) ? "Wired" : "Wireless");
		Log("\tConnection Type:%s\r\n", FLAG(INTERFACE) ? "Wired" : "Wireless");

		printf(CYAN "\tSSID (Wireless Only):" WHITE " %s\n", netconfig->connection[slot].ssid);
		Log("\tSSID (Wireless Only):%s\r\n", netconfig->connection[slot].ssid);

		printf(CYAN "\tMTU:" WHITE " %u (%s)\n", netconfig->connection[slot].mtu, (netconfig->connection[slot].mtu) ? "Manual" :"Default");
		Log("\tMTU:%u (%s)\r\n", netconfig->connection[slot].mtu, (netconfig->connection[slot].mtu) ? "Manual" : "Default");

		char ipaddress[8];
		sprintf(ipaddress, "%u.%u.%u.%u", netconfig->connection[slot].ip[0], netconfig->connection[slot].ip[1], netconfig->connection[slot].ip[2], netconfig->connection[slot].ip[3]);		
		printf(CYAN "\tStatic IP:" WHITE " %s\n", (strcmp(ipaddress, "0.0.0.0")) ? ipaddress : "Not set");
		Log("\tStatic IP:%s\r\n", (strcmp(ipaddress, "0.0.0.0")) ? ipaddress : "Not set");

		printf(CYAN "\tEncryption:" WHITE " %s\n", vencryption[netconfig->connection[slot].encryption]);
		Log("\tEncryption:%s\r\n", vencryption[netconfig->connection[slot].encryption]);

		NetworkEncryption(slot);

		printf(CYAN "\tConnection Test Passed:" WHITE " %s\n", FLAG(INTERNET_TEST) ? "Yes" : "No");
		Log("\tConnection Test Passed:%s\r\n", FLAG(INTERNET_TEST) ? "Yes" : "No");

		printf(CYAN "\tSelected:" WHITE " %s\n", FLAG(CONNECTION_SELECTED) ? "Yes" : "No");
		Log("\tSelected:%s\r\n", FLAG(CONNECTION_SELECTED) ? "Yes" : "No");

		NetworkProxy(netconfig->connection[slot].proxy_settings);

		printf(CYAN "\tIP Source:" WHITE " %s\n", FLAG(IP_SOURCE) ? "DHCP" : "Manual");
		Log("\tIP Source:%s\r\n", FLAG(IP_SOURCE) ? "DHCP" : "Manual");

		printf(CYAN "\tDNS Source:" WHITE " %s\n", FLAG(DNS_SOURCE) ? "DHCP" : "Manual");
		Log("\tDNS Source:%s\r\n", FLAG(DNS_SOURCE) ? "DHCP" : "Manual");
	}

	if (slot < 2) {
		CHANGE_COLOR(YELLOW);
		printf("\nPress any key to continue\n");
		pressanykey();
	}
	return;
}
